﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Tests
//  File name:	TestContext.cs
//  Developer:	Solomatov Igor
//  Created:	03.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections.Specialized;
using System.Diagnostics;
using Microsoft.SharePoint;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Smart.Common;
using Smart.Common.Entities;

namespace Smart.Documents.Tests
{
	[TestClass]
	public class TestContext
	{
		[TestMethod]
		public void WebScopeGenerated()
		{
			string c1 = null;
			string c2 = null;
			string c3 = null;
			string c4 = null;
			string c5 = null;
			string c6 = null;

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   using (var sc = WebEntityScope.CurrentWeb)
									   {
										   var conf = sc.Get<WebEntity>(Common.Const.Configuration.MainListUrl);

										   var allitems = conf.All;

										   c1 = (allitems != null).ToString() + (allitems != null && allitems.Count > 0);

										   var allisok = true;

										   foreach (var entity in allitems)
										   {
											   if (entity.ID.IsEmpty || entity.ID.Int != ((SPListItem)entity.Source).ID ||
												   entity.Title != ((SPListItem)entity.Source).Title)
											   {
												   allisok = false;

												   H.LT("************ Mapper error: {0}: {1}, {2}: {3} ************",
														entity.ID.Int, ((SPListItem)entity.Source).ID,
														entity.Title, ((SPListItem)entity.Source).Title);

												   break;
											   }
										   }

										   c1 += allisok.ToString();

										   SPServices.Configuration.SetUserValue("TestContext", "testValue");

										   //var l0items =
										   //	conf.Query.Where.Eq(Common.Const.Configuration.Level.ToString(), 0).Executor.Execute();

										   //c2 = (l0items != null).ToString() + (l0items != null && l0items.Count > 0);

										   SPServices.Configuration.RemoveUserValue("TestContext");

										   //var l2items =
										   //	conf.Query.Where.Eq(Common.Const.Configuration.Level.ToString(), 2).Executor.Execute();

										   //c3 = (l2items != null).ToString() + (l2items != null && l2items.Count > 0);
									   }

									   using (var srw = WebEntityScope.GetScope(SPH.GetWeb()))
									   {
										   var conf = srw.Get<WebEntity>(Common.Const.Configuration.MainListUrl);

										   var allitems = conf.All;

										   c4 = (allitems != null).ToString() + (allitems != null && allitems.Count > 0);

										   SPServices.Configuration.SetUserValue("TestContext", "testValue");

										   //var l0items =
										   //	conf.Query.Where.Eq(Common.Const.Configuration.Level.ToString(), 0).Executor.Execute();

										   //c5 = (l0items != null).ToString() + (l0items != null && l0items.Count > 0);

										   SPServices.Configuration.RemoveUserValue("TestContext");

										   //var l2items =
										   //	conf.Query.Where.Eq(Common.Const.Configuration.Level.ToString(), 2).Executor.Execute();

										   //c6 = (l2items != null).ToString() + (l2items != null && l2items.Count > 0);
									   }
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual("TrueTrueTrue", c1);
			Assert.AreEqual("TrueTrue", c2);
			Assert.AreEqual("TrueTrue", c3);

			Assert.AreEqual("TrueTrue", c4);
			Assert.AreEqual("TrueTrue", c5);
			Assert.AreEqual("TrueTrue", c6);
		}

		public const string l1 = "test1";
		public const string l2 = "test2";

		[Entity("KTest1")]
		public class KTest1 : WebEntity
		{
		}

		[Entity("KTest2")]
		public class KTest2 : WebEntity
		{
			[Field("Choice")]
			public string Choice { get; set; }

			[Field("Date")]
			public DateTime Date { get; set; }

			[Field("Bool")]
			public bool Bool { get; set; }

			[Field("Int")]
			public int Int { get; set; }

			[Field("Double")]
			public double Double { get; set; }

			[Field("Lookup")]
			public LookupValue Lookup { get; set; }

			[Field("LookupMulti")]
			public LookupValueCollection LookupMulti { get; set; }

			[Field("User")]
			public UserValue User { get; set; }

			[Field("UserMulti")]
			public UserValueCollection UserMulti { get; set; }

			[Field("ChoiceMulti")]
			public ChoiceValueCollection ChoiceMulti { get; set; }

			[Field("Link")]
			public LinkValue Link { get; set; }
		}

		public interface IKTestCtx : IWebEntityScope
		{
			IEntityFacade<KTest1> Test1 { get; }
			IEntityFacade<KTest2> Test2 { get; }
		}

		public class KTestCtx : WebEntityScope, IKTestCtx
		{
			public static IKTestCtx Current
			{
				get { return EntityScope.GetScope<IKTestCtx>("TestScopeName"); }
			}

			public IEntityFacade<KTest1> Test1
			{
				get { return Get<KTest1>(l1); }
			}

			public IEntityFacade<KTest2> Test2
			{
				get { return Get<KTest2>(l2); }
			}
		}

		public void RegScope()
		{
			var web = SPH.GetRootWeb();

			using (new UnsafeUpdate(web))
			{
				var config = SPServices.Configuration;

				config.SetValue(web, "Scope.TestScopeName", "TestScopeType\n/\r\nTest1#Lists/Test1#true#0:0:10##Low\nTest2#Test2#false#0:0:10#0:0:5#High");

				SPServices.Cache.Clear();

				EntityFactory.Register<KTest1>();
				EntityFactory.Register<KTest2>();

				EntityScope.Register<KTestCtx, IKTestCtx>("TestScopeType");

				try
				{
					var lst = web.Lists[l1];
					lst.Delete();
				}
				catch
				{
				}

				try
				{
					var lst = web.Lists[l2];
					lst.Delete();
				}
				catch
				{
				}

				var lid1 = web.Lists.Add(l1, "test list 1", SPListTemplateType.GenericList);
				var lid2 = web.Lists.Add(l2, "test list 2", SPListTemplateType.GenericList);

				var mcv = new StringCollection { "choice1", "choice2", "choice3" };

				var lst1 = web.GetListById(lid1);

				var lst2 = web.GetListById(lid2);

				lst2.Fields.Add("Choice", SPFieldType.Choice, false, false, mcv);
				lst2.Fields.Add("Date", SPFieldType.DateTime, false);
				lst2.Fields.Add("Bool", SPFieldType.Boolean, false);
				lst2.Fields.Add("Int", SPFieldType.Integer, false);
				lst2.Fields.Add("Double", SPFieldType.Number, false);
				lst2.Fields.AddLookup("Lookup", lid1, false);
				lst2.Fields.AddLookup("LookupMulti", lid1, false);
				lst2.Fields.Add("User", SPFieldType.User, false);
				lst2.Fields.Add("UserMulti", SPFieldType.User, false);
				lst2.Fields.Add("User", SPFieldType.User, false);
				lst2.Fields.Add("ChoiceMulti", SPFieldType.MultiChoice, false, false, mcv);
				lst2.Fields.Add("Link", SPFieldType.URL, false);

				var lm = (SPFieldLookup)lst2.Fields["LookupMulti"];
				lm.AllowMultipleValues = true;
				lm.Update();

				var um = (SPFieldUser)lst2.Fields["UserMulti"];
				um.AllowMultipleValues = true;
				um.Update();

				var li11 = lst1.AddItem();
				li11["Title"] = "li11";
				li11.Update();

				var li12 = lst1.AddItem();
				li12["Title"] = "li12";
				li12.Update();

				var li13 = lst1.AddItem();
				li13["Title"] = "li13";
				li13.Update();


				var li21 = lst2.AddItem();
				li21["Title"] = "li21";
				li21["Choice"] = "choice1";
				li21["Date"] = DateTime.Today;
				li21["Bool"] = true;
				li21["Int"] = 21;
				li21["Double"] = 2.1;
				li21["Lookup"] = li11.ID;
				li21["LookupMulti"] =
					new SPFieldLookupValueCollection { new SPFieldLookupValue(li11.ID, ""), new SPFieldLookupValue(li12.ID, "") }.ToString
						();
				li21["User"] = web.CurrentUser.ID;
				li21["UserMulti"] = new SPFieldUserValueCollection { new SPFieldUserValue(web, web.CurrentUser.ID, web.CurrentUser.LoginName) };
				li21["ChoiceMulti"] = "choice1;#choice2";
				li21["Link"] = "http://www.mail.ru, Mail.Ru";
				li21.Update();

				var li22 = lst2.AddItem();
				li22["Title"] = "li22";
				li22["Choice"] = "choice2";
				li22["Date"] = DateTime.Today.AddDays(1);
				li22["Bool"] = false;
				li22["Int"] = 22;
				li22["Double"] = 2.2;
				li22["Lookup"] = li12.ID;
				li22["LookupMulti"] =
					new SPFieldLookupValueCollection { new SPFieldLookupValue(li12.ID, ""), new SPFieldLookupValue(li13.ID, "") }.ToString
						();
				li22["User"] = web.CurrentUser.ID;
				li22["UserMulti"] = new SPFieldUserValueCollection { new SPFieldUserValue(web, web.CurrentUser.ID, web.CurrentUser.LoginName) };
				li22["ChoiceMulti"] = "choice2;#choice3";
				li22["Link"] = "http://www.gmail.com, GMail.com";
				li22.Update();

				var li23 = lst2.AddItem();
				li23["Title"] = "li23";
				li23.Update();
			}
		}

		public IKTestCtx GetScope()
		{
			return KTestCtx.Current;
		}

		public void UnregScope()
		{
			var web = SPH.GetWeb();

			using (new UnsafeUpdate(web))
			{
				var config = SPServices.Configuration;

				try
				{
					web.Lists[l1].Delete();
				}
				catch
				{
				}
				try
				{
					web.Lists[l2].Delete();
				}
				catch
				{
				}

				EntityFactory.Unregister(typeof(KTest1));
				EntityFactory.Unregister(typeof(KTest2));

				EntityScope.Unregister<IKTestCtx>("TestScopeType");

				config.RemoveValue(web, "Scope.TestScopeName");
			}
		}

		[TestMethod]
		public void WebScopeNamed()
		{
			string c1 = null;
			string c2 = null;
			string c3 = null;
			string c4 = null;
			string c5 = null;
			string c6 = null;

			var sw1_nc = new Stopwatch();
			var sw2_nc = new Stopwatch();
			var sw1_c = new Stopwatch();
			var sw2_c = new Stopwatch();

			var sw3_nc = new Stopwatch();
			var sw3_c = new Stopwatch();

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   RegScope();

									   H.LT("WebScopeNamed: compiling EntityMappers...");
									   var sw_cem = new Stopwatch();
									   sw_cem.Start();

									   var m1 = EntityMapperExts.ReadCacheMapper(typeof(KTest1).FullName, typeof(KTest1), WebEntityMapper.Current.GetConfig);
									   var m2 = EntityMapperExts.ReadCacheMapper(typeof(KTest2).FullName, typeof(KTest2), WebEntityMapper.Current.GetConfig);

									   sw_cem.Stop();
									   H.LT("WebScopeNamed: compiled EntityMappers, time: {0}", sw_cem.Elapsed);

									   sw1_nc.Start();
									   sw2_nc.Start();
									   using (var sc = GetScope())
									   {
										   sw2_nc.Stop();

										   sw3_nc.Start();
										   var allitems = sc.Test1.All;
										   sw3_nc.Stop();

										   c1 = (allitems != null).ToString() + (allitems != null && allitems.Count == 3);

										   var allisok = true;

										   foreach (var entity in allitems)
										   {
											   if (entity.ID.IsEmpty || entity.ID.Int != ((SPListItem)entity.Source).ID ||
												   entity.Title != ((SPListItem)entity.GetSource()).Title)
											   {
												   allisok = false;

												   H.LT("************ Mapper error: {0}: {1}, {2}: {3} ************",
														entity.ID.Int, ((SPListItem)entity.Source).ID,
														entity.Title, ((SPListItem)entity.Source).Title);

												   break;
											   }
										   }

										   c1 += allisok.ToString();

										   var l0items =
											   sc.Test2.Query.Where.Eq("Int", 21).Executor.Execute();

										   c2 = (l0items != null).ToString() + (l0items != null && l0items.Count == 1);

										   var l2items =
											   sc.Test2.Query.Where.Geq("Double", 2.2).Executor.Execute();

										   c3 = (l2items != null).ToString() + (l2items != null && l2items.Count == 1);
									   }
									   sw1_nc.Stop();

									   sw1_c.Start();
									   sw2_c.Start();
									   using (var sc = GetScope())
									   {
										   sw2_c.Stop();

										   sw3_c.Start();
										   var allitems = sc.Test1.All;
										   sw3_c.Stop();

										   c4 = (allitems != null).ToString() + (allitems != null && allitems.Count == 3);

										   var allisok = true;

										   foreach (var entity in allitems)
										   {
											   if (entity.ID.IsEmpty)
											   {
												   allisok = false;

												   H.LT("************ Mapper error: {0}: {1}, {2}: {3} ************",
														entity.ID.Int, null,
														entity.Title, null);

												   break;
											   }
										   }

										   c4 += allisok.ToString();

										   var l0items =
											   sc.Test2.Query.Where.Eq("Int", 21).Executor.Execute();

										   c5 = (l0items != null).ToString() + (l0items != null && l0items.Count == 1);

										   var l2items =
											   sc.Test2.Query.Where.Geq("Double", 2.2).Executor.Execute();

										   c6 = (l2items != null).ToString() + (l2items != null && l2items.Count == 1);
									   }
									   sw1_c.Stop();

									   H.LT("************ List cache timings, non-cached: {0}, cached: {1} ************",
											sw3_nc.Elapsed, sw3_c.Elapsed);
									   H.LT("************ Scope cache timings, non-cached: {0}, cached: {1} ************",
											sw2_nc.Elapsed, sw2_c.Elapsed);
									   H.LT("************ Overall cache timings, non-cached: {0}, cached: {1} ************",
											sw1_nc.Elapsed, sw1_c.Elapsed);

									   UnregScope();
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual("TrueTrueTrue", c1);
			Assert.AreEqual("TrueTrue", c2);
			Assert.AreEqual("TrueTrue", c3);

			Assert.AreEqual("TrueTrueTrue", c4);
			Assert.AreEqual("TrueTrue", c5);
			Assert.AreEqual("TrueTrue", c6);

			Assert.AreEqual(true, sw3_nc.Elapsed.TotalMilliseconds > sw3_c.Elapsed.TotalMilliseconds * 30,
							string.Format("List cache is not working, non-cached: {0}, cached: {1}", sw3_nc.Elapsed,
										  sw3_c.Elapsed));
			Assert.AreEqual(true, sw2_nc.Elapsed.TotalMilliseconds > sw2_c.Elapsed.TotalMilliseconds * 300,
							string.Format("Scope cache is not working, non-cached: {0}, cached: {1}", sw2_nc.Elapsed,
										  sw2_c.Elapsed));
			Assert.AreEqual(true, sw1_nc.Elapsed.TotalMilliseconds > sw1_c.Elapsed.TotalMilliseconds * 100,
							string.Format("Overall cache is not working, non-cached: {0}, cached: {1}", sw1_nc.Elapsed,
										  sw1_c.Elapsed));
		}

		[TestMethod]
		public void EntityMapper()
		{
			string c1 = null;
			string c2 = null;
			string c3 = null;
			string c4 = null;
			string c5 = null;

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   RegScope();

									   using (var sc = GetScope())
									   {
										   H.LT("sc.Web.RootFolder.Url={0}", sc.Web.RootFolder.Url);

										   var allitems = sc.Test2.Query.Sort("ID", true).Executor.Execute();

										   if (allitems.Count != 3)
											   throw new Exception("IS NOT WORKING!!!");

										   var i1 = allitems[0];
										   c1 =
											   (i1.ID.Int == 1).ToString() +
											   (i1.Title == "li21") +
											   (i1.Choice == "choice1") +
											   (i1.Date.Date == DateTime.Today) +
											   i1.Bool +
											   (i1.Int == 21) +
											   (Math.Abs(i1.Double - 2.1) < 0.0001) +
											   (i1.Lookup.ToString() == "1;#li11") +
											   (i1.LookupMulti.ToString() == "1;#li11;#2;#li12") +
											   (i1.User.ToString() == sc.Web.CurrentUser.ID + ";#" + sc.Web.CurrentUser.Name) +
											   (i1.UserMulti.ToString() == sc.Web.CurrentUser.ID + ";#" + sc.Web.CurrentUser.Name) +
											   (i1.ChoiceMulti.ToString() == "choice1;#choice2") +
											   (i1.Link.ToString() == "http://www.mail.ru, Mail.Ru");

										   H.LT("i1.Item.Url={0}", i1.GetItem().Url);

										   var i2 = allitems[1];
										   c2 =
											   (i2.ID.Int == 2).ToString() +
											   (i2.Title == "li22") +
											   (i2.Choice == "choice2") +
											   (i2.Date.Date == DateTime.Today.AddDays(1)) +
											   (i2.Bool == false) +
											   (i2.Int == 22) +
											   (Math.Abs(i2.Double - 2.2) < 0.0001) +
											   (i2.Lookup.ToString() == "2;#li12") +
											   (i2.LookupMulti.ToString() == "2;#li12;#3;#li13") +
											   (i2.User.ToString() == sc.Web.CurrentUser.ID + ";#" + sc.Web.CurrentUser.Name) +
											   (i2.UserMulti.ToString() == sc.Web.CurrentUser.ID + ";#" + sc.Web.CurrentUser.Name) +
											   (i2.ChoiceMulti.ToString() == "choice2;#choice3") +
											   (i2.Link.ToString() == "http://www.gmail.com, GMail.com");

										   H.LT("i2.Item.Url={0}", i2.GetItem().Url);

										   var i3 = allitems[2];
										   c3 =
											   (i3.ID.Int == 3).ToString() +
											   (i3.Title == "li23") +
											   (i3.Choice == null) +
											   (i3.Date.IsEmpty()) +
											   (i3.Bool == false) +
											   (i3.Int == 0) +
											   (i3.Double == 0.0) +
											   (i3.Lookup.IsEmpty) +
											   (i3.LookupMulti.IsEmpty) +
											   (i3.User.IsEmpty) +
											   (i3.UserMulti.IsEmpty) +
											   (i3.ChoiceMulti.IsEmpty) +
											   (i3.Link.IsEmpty);

										   H.LT("i3.Item.Url={0}", i3.GetItem().Url);

										   var i4 = sc.Test2.Create();
										   i4.Title = "li24";
										   i4.Choice = "choice2";
										   i4.Date = DateTime.Today.AddDays(2);
										   i4.Bool = false;
										   i4.Int = 24;
										   i4.Double = 2.4;
										   i4.Lookup.Set(2);
										   i4.LookupMulti.Set(2, 3);
										   i4.User.Set(sc.Web.CurrentUser.ID);
										   i4.UserMulti.Ensure(sc.Web.CurrentUser);
										   i4.ChoiceMulti.Set("choice2", "choice3");
										   i4.Link.Set("http://www.gmail.com", "GMail.com");
										   i4.Save();

										   H.LT("i4.Item.Url={0}", i4.GetItem().Url);

										   c4 =
											   (i4.ID.Int == 4).ToString() +
											   (i4.Title == "li24") +
											   (i4.Choice == "choice2") +
											   (i4.Date == DateTime.Today.AddDays(2)) +
											   (i4.Bool == false) +
											   (i4.Int == 24) +
											   (Math.Abs(i4.Double - 2.4) < 0.0001) +
											   (i4.Lookup == new LookupValue(2)) +
											   (i4.LookupMulti.Equals(new Identifier[] { 2, 3 })) +
											   (i4.User == new UserValue(sc.Web.CurrentUser.ID)) +
											   (i4.UserMulti.Equals(new Identifier[] { sc.Web.CurrentUser.ID })) +
											   (i4.ChoiceMulti.Equals(new[] { "choice2", "Choice3" })) +
											   (i4.Link.Url.EqIC("http://www.gmail.com"));

										   var i4t = sc.Test2.GetById(i4.ID);

										   c5 =
											   (i4.ID == i4t.ID).ToString() +
											   (i4.Title == i4t.Title) +
											   (i4.Choice == i4t.Choice) +
											   (i4.Date == i4t.Date) +
											   (i4.Bool == i4t.Bool) +
											   (i4.Int == i4t.Int) +
											   (i4.Double == i4t.Double) +
											   (i4.Lookup == i4t.Lookup) +
											   (i4.LookupMulti.Equals(i4t.LookupMulti)) +
											   (i4.User == i4t.User) +
											   (i4.UserMulti.Equals(i4t.UserMulti)) +
											   (i4.ChoiceMulti.Equals(i4t.ChoiceMulti)) +
											   (i4.Link == i4t.Link);

										   H.LT("i4t.Item.Url={0}", i4t.GetItem().Url);
									   }

									   UnregScope();
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue", c1);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue", c2);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue", c3);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue", c4);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue", c5);
		}
	}
}